//package com.csthink.mysql.interceptor;
//
//import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
//import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
//import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
//import com.baomidou.mybatisplus.extension.parser.JsqlParserSupport;
//import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
//import com.google.common.collect.Maps;
//import lombok.extern.slf4j.Slf4j;
//import net.sf.jsqlparser.JSQLParserException;
//import net.sf.jsqlparser.parser.CCJSqlParserUtil;
//import net.sf.jsqlparser.statement.Statement;
//import net.sf.jsqlparser.statement.Statements;
//import net.sf.jsqlparser.statement.delete.Delete;
//import net.sf.jsqlparser.statement.select.PlainSelect;
//import net.sf.jsqlparser.statement.select.Select;
//import net.sf.jsqlparser.statement.update.Update;
//import org.apache.commons.lang3.StringUtils;
//import org.apache.ibatis.executor.statement.StatementHandler;
//import org.apache.ibatis.mapping.BoundSql;
//import org.apache.ibatis.mapping.MappedStatement;
//import org.apache.ibatis.mapping.SqlCommandType;
//import org.springframework.core.env.Environment;
//
//import java.sql.Connection;
//import java.util.List;
//import java.util.concurrent.ConcurrentHashMap;
//
///**
// * @author <a href="mailto:security.2009@live.cn">Mars</a>
// * @since 2023-09-10
// */
//@Slf4j
//public class BlockUnauthorizedAccessInterceptor extends JsqlParserSupport implements InnerInterceptor {
//
//    private static final String ACCOUNT_ID = "account_id";
//    private static final ConcurrentHashMap.KeySetView<String, Boolean> fineSqlMd5Set = ConcurrentHashMap.newKeySet();
//
//    @Override
//    public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {
//        if (needPatchSwitchOff()) {
//            return;
//        }
//        PluginUtils.MPStatementHandler handler = PluginUtils.mpStatementHandler(sh);
//        MappedStatement ms = handler.mappedStatement();
//        SqlCommandType sct = ms.getSqlCommandType();
//        if (sct == SqlCommandType.SELECT || sct == SqlCommandType.UPDATE || sct == SqlCommandType.DELETE) {
//            if (InterceptorIgnoreHelper.willIgnoreBlockAttack(ms.getId())) {
//                return;
//            }
//            BoundSql boundSql = handler.boundSql();
//            String sql = boundSql.getSql();
//            try {
//                Statements statements = CCJSqlParserUtil.parseStatements(sql);
//                List<Statement> statementsStatements = statements.getStatements();
//                for (int i = 0; i < statementsStatements.size(); i++) {
//                    Statement statement = statementsStatements.get(i);
//                    if (fineSqlMd5Set.contains(statement.toString())) {
//                        continue;
//                    }
//                    if (statement instanceof Select) {
//                        this.processSelect((Select) statement, i, statement.toString(), null);
//                    } else if (statement instanceof Update) {
//                        this.processUpdate((Update) statement, i, statement.toString(), null);
//                    } else if (statement instanceof Delete) {
//                        this.processDelete((Delete) statement, i, statement.toString(), null);
//                    }
//                }
//            } catch (JSQLParserException e) {
//                throw ExceptionUtils.mpe("Failed to process, Error SQL: %s", e, sql);
//            }
//        }
//    }
//
//    @Override
//    protected void processSelect(Select select, int index, String sql, Object obj) {
//        String accountId = AuthenticationInfoUtil.getAccountId();
//        if (StringUtils.isBlank(accountId)) {
//            return;
//        }
//        try {
//            int cnt = JSqlParserUtil.patchCondition((PlainSelect) select.getSelectBody(), Maps.immutableEntry(ACCOUNT_ID, accountId));
//            if (cnt == 0) {
//                fineSqlMd5Set.add(select.toString());
//            } else {
//                log.debug("original SQL: {}", sql);
//                log.debug("patched SQL: {}", select.toString());
//            }
//        } catch (Exception e) {
//            log.error("add condition to select error", e);
//            try {
//                PlainSelect plainSelect = (PlainSelect) CCJSqlParserUtil.parse(sql);
//                ((PlainSelect) select.getSelectBody()).setWhere(plainSelect.getWhere());
//            } catch (JSQLParserException e1) {
//                log.error("backup sql parse error", e1);
//            }
//        }
//    }
//
//    @Override
//    protected void processDelete(Delete delete, int index, String sql, Object obj) {
//        String accountId = AuthenticationInfoUtil.getAccountId();
//        if (StringUtils.isBlank(accountId)) {
//            return;
//        }
//        try {
//            int cnt = JSqlParserUtil.patchCondition(delete, Maps.immutableEntry(ACCOUNT_ID, accountId));
//            if (cnt == 0) {
//                fineSqlMd5Set.add(delete.toString());
//            } else {
//                log.debug("original SQL: {}", sql);
//                log.debug("patched SQL: {}", delete.toString());
//            }
//        } catch (Exception e) {
//            log.error("add condition to delete error", e);
//            try {
//                delete.setWhere(((Delete) CCJSqlParserUtil.parse(sql)).getWhere());
//            } catch (JSQLParserException e1) {
//                log.error("backup sql parse error", e1);
//            }
//        }
//    }
//
//    @Override
//    protected void processUpdate(Update update, int index, String sql, Object obj) {
//        String accountId = AuthenticationInfoUtil.getAccountId();
//        if (StringUtils.isBlank(accountId)) {
//            return;
//        }
//        try {
//            int cnt = JSqlParserUtil.patchCondition(update, Maps.immutableEntry(ACCOUNT_ID, accountId));
//            if (cnt == 0) {
//                fineSqlMd5Set.add(update.toString());
//            } else {
//                log.debug("original SQL: {}", sql);
//                log.debug("patched SQL: {}", update.toString());
//            }
//        } catch (Exception e) {
//            log.error("add condition to update error", e);
//            try {
//                update.setWhere(((Update) CCJSqlParserUtil.parse(sql)).getWhere());
//            } catch (JSQLParserException e1) {
//                log.error("backup sql parse error", e1);
//            }
//        }
//    }
//
//    private boolean needPatchSwitchOff() {
//        Environment environment = SpringUtil.getBean(Environment.class);
//        return !environment.getProperty("mybatis-plus.configuration.patch_account_condition", Boolean.class, false);
//    }
//}
